from django.db import models
from datetime import datetime


# 1. 定义模型类
# 模型类必须要直接或者间接继承于 models.Model
class BaseModel(models.Model):
    """公共模型[公共方法和公共字段]"""
    # created_time = models.IntegerField(default=0,verbose_name="创建时间")
    created_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    # auto_now_add 当数据添加时，设置当前时间为默认值
    # auto_now= 当数据添加/更新时，设置当前时间为默认值
    updated_time = models.DateTimeField(auto_now=True)

    class Meta(object):
        abstract = True  # 设置当前模型为抽象模型，当系统运行时，不会任务这是一个数据表对应的模型。


class Student(BaseModel):
    """Student模型类"""
    # 1. 字段[数据库表字段对应]
    SEX_CHOICES = (
        (0, '女'),
        (1, '男'),
        (2, '保密'),
    )

    # 字段名 = models.数据类型(约束选项1，约束选项2，verbose_name="注释")
    # SQL: id bigint primary_key auto_increment not null comment="主键",
    # id = models.AutoField(primary_key=True, null=False, verbose_name="主键")
    # django会自动在创建数据表的时候生成id主键/还设置了一个调用别名：pk

    # SQL: name varchar(20) not null comment="姓名"
    # SQL: key(name),
    name = models.CharField(max_length=20, db_index=True, verbose_name="姓名")

    # SQL: age smallint not null comment="年龄"
    age = models.SmallIntegerField(verbose_name="年龄")

    # SQL: sex tinyint not null comment="性别"
    # sex = models.BooleanField(verbose_name="性别")
    sex = models.SmallIntegerField(choices=SEX_CHOICES, default=2)

    # SQL: class varchar(5) not null comment="班级"
    # SQL: key(class)
    classmate = models.CharField(db_column="class", max_length=5, db_index=True, verbose_name="班级")
    # SQL: description longtext default "" not null comment="个性签名"
    description = models.TextField(default="", verbose_name="个性签名")

    # 2. 数据表结构信息
    class Meta:
        db_table = 'tb_student'
        # 指明数据库表名，如果没有指定表名，则默认为子应用目录名_模型名称，例如：users_student
        verbose_name = "学生信息表"
        # 在admin站点中显示的名称

        verbose_name_plural = verbose_name  # 显示的复数？？？名称？？

    # 3. 自定义数据库操作方法
    def __str__(self):
        """定义每个数据对象的显示信息"""


# 2. 数据迁移
# python manage.py makemigrations
# python manage.py miarage

# 3. 数据库基本操作
# 3.1 添加记录
# save, create
# 3.2 基础查询：
# orm中针对查询结果的限制，提供了一个查询集QuerySet, 是针对查询结果进行保存数据的一个类型，可以通过了解这个QuerySet进行使用，达到查询优化，或者限制查询结果数量的zuoyong
# all
student = Student.all() # 查询所有函数api，返回的是一个queryset，非常接近列表数据，里面的元素是模型类对象
print('student>>>:', student)
# first last filter exclude get order_by count exist values values_list distinct

# 3.3 模糊查询
# contains, startswith, endwith isnull, 比较查询，
# 模糊查询range， in， 日期查询
Student.object.filter(name__contains = "华")

# 3.4 进阶查询
# F查询: 两个属性之间的比较， 使用F对象
# Q查询: 多个过滤器逐个调用标识逻辑与关系，同sql语句中where部分的and关键字
from django.db.models import F
student_list = Student.objects.exclude(created_time=F('updated_time'))
# 聚合函数aggregate
# 分组函数annotate
# 原生sql

# 3.5 修改记录
# 使用save更新数据
# update 更新

# 3.6 删除记录
# 模型类对象.delete
# 模型类.object.filter().delete()


######################################################
# 4. 创建关联模型

from django.db import models


# Create your models here.


class Clas(models.Model):
    name = models.CharField(max_length=32, unique=True, verbose_name="班级名称")

    class Meta:
        db_table = "db_class"


class Course(models.Model):
    title = models.CharField(max_length=32, verbose_name="课程名称")

    # 多对多时关系表的创建在哪个表中都可以
    # students = models.ManyToManyField("Student", db_table="db_stu2course")

    class Meta:
        db_table = "db_course"


class Student(models.Model):
    gender_choices = (
        (0, '女'),
        (1, '男'),
        (2, '保密'),
    )

    name = models.CharField(max_length=32, unique=True, verbose_name="姓名")
    age = models.SmallIntegerField(verbose_name="年龄", default=18)
    gender = models.SmallIntegerField(choices=gender_choices)

    # 建立一对多的关系：会在数据库中创建一个关联字段，名称叫做clas_id
    # 一对多的关系必须在多的表中建立，多对多则不用
    clas = models.ForeignKey(to="Clas", on_delete=models.CASCADE, db_constraint=False)
    # db_constraint=False表示不加约束，则仅仅创建一个clas_id的字段，没有外键约束

    # 建立多对多的关系：创建第三张关系表
    courses = models.ManyToManyField("Course", db_table="db_stu2course")
    # 这句话可以帮我们创建第三张关系表，里面有三个字段。

    # 一对一的关系：建立关联字段，在数据库中创建一个关联字段，名称叫做stu_detail_id
    stu_detail = models.OneToOneField("StudentDetail", on_delete=models.CASCADE)

    class Meta:
        db_table = "db_student"


class StudentDetail(models.Model):
    tel = models.CharField(max_length=11)
    addr = models.CharField(max_length=32)

    class Meta:
        db_table = "db_stu_detail"

############################################################
# 5. 关联添加
# 一对一与一对多

############################################################

# 6. 关联查询
# 6.1 基于对象查询(子查询)

# 6.2 基于双下划线查询(join查询)
# 6.3 关联分组查询